package services

import (
	"context"
	"errors"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"google.golang.org/grpc"
	"log"
	"math/rand"
	"time"
	codeserver "tokenserver/bproto"
	tokenservice "tokenserver/proto"
)

type ServiceAI struct {}


func UseRedis () (redis.Conn , error) {
	return redis.Dial("tcp" , ":6379")
}

func UseMysql () (*gorm.DB , error){
	return gorm.Open("mysql" , "root:123456@/oauth?charset=utf8&parseTime=True&loc=Local")
}

func  GetRandomString(l int) string {
	str := "0123456789abcdefghijklmnopqrstuvwxyz"
	bytes := []byte(str)
	result := []byte{}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < l; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}
	return string(result)
}

type Client struct{
	Id int
	Name string
	Secret string
}
func Isvalid (request *codeserver.ValidRequest) bool {
	lis , err := grpc.Dial("127.0.0.1:8081" , grpc.WithInsecure())
	if err != nil {
		log.Println(err)
		return false
	}
	client := codeserver.NewCodeServerClient(lis)
	rep , err := client.Isvalid(context.Background() , request)
	if err != nil {
		log.Println(err)
		return false
	}
	if rep.IsValid {
		return true
	} else {
		return false
	}
}

func GetUserId (code string) string {
	con , _ := UseRedis()
	rep , _ := con.Do("get" , code)
	return  string(rep.([]uint8))

}

func (s ServiceAI) GetToken(ctx context.Context, req *tokenservice.ReqGetToken) (*tokenservice.RepGetToken, error) {
	if !Isvalid(&codeserver.ValidRequest{UserId: req.UserId , Code: req.Code}) {
		return nil , errors.New("code is not valid ")
	}
	con , err := UseRedis()
	if err != nil {
		return nil , errors.New("connet database default")
	}
	User := GetUserId(req.Code)
	mysql , err := UseMysql()
	if err != nil {
		log.Println("get secrete default")
	}
	var c Client
	mysql.Table("client").Where("id = ?",req.ClientId).Find(&c)
	fmt.Println(c)
	if c.Secret !=req.Secret {
		fmt.Println(c.Secret , " " , req.Secret)
		return nil , errors.New("not pi pei")
	}
	str := GetRandomString(11)
	_ , err = con.Do("hset" , User , "token" ,  str)
	con.Do("EXPIRE" , User , 120)
	con.Do("set" , str , User , "EX" , 120)
	if err != nil {
		return nil , err
	}
	return &tokenservice.RepGetToken{Toen: str} , nil
}

func (s ServiceAI) IsValidToken(ctx context.Context, req *tokenservice.IsValidTokenReq) (*tokenservice.IsValidToeknRep, error) {
	con , err := UseRedis()
	if err != nil {
		log.Println(err)
		return nil , err
	}
	r , err := con.Do("get" ,req.Token)
	if err != nil {
		return nil , err
	}
	if r == nil {
		return &tokenservice.IsValidToeknRep{IsValid: false} , nil
	}
	rep := string(r.([]uint8))
	return &tokenservice.IsValidToeknRep{IsValid: true , Userid: rep} , nil
}